import 'dart:io';
import 'dart:typed_data';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:speex_demo/ai_voice_controller/ai_device_voice_controller_manager.dart';
import 'package:speex_demo/derucci_iat_stream.dart';
import 'package:speex_demo/speex_ffi.dart';

import 'record_demo.dart';
import 'sound_demo.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Speex Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Speex Demo Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    RecordDemo.instance.initRecorder();
    SoundDemo.instance.initPlayer();
    super.initState();
  }

  Stream<Uint8List> pcmFileToStream(String assetPath, {int chunkSize = 640}) async* {
    // 读取整个 PCM 文件
    final data = await rootBundle.load(assetPath);
    final bytes = data.buffer.asUint8List();

    int offset = 0;
    while (offset < bytes.length) {
      final end = (offset + chunkSize < bytes.length) ? offset + chunkSize : bytes.length;
      yield bytes.sublist(offset, end);
      offset = end;
      await Future.delayed(const Duration(milliseconds: 20)); // 模拟实时流
    }
  }

  /// 将 assets Speex 文件转成实时流
  Stream<Uint8List> speexFileToFrameStream(String assetPath, {int frameSize = 60}) async* {
    final data = await rootBundle.load(assetPath);
    final bytes = data.buffer.asUint8List();

    int offset = 0;
    while (offset + frameSize <= bytes.length) {
      final frame = bytes.sublist(offset, offset + frameSize);
      offset += frameSize;

      yield frame;

      // 模拟实时播放 (16kHz 宽带 → 每帧20ms)
      await Future.delayed(const Duration(milliseconds: 20));
    }
  }

  final BytesBuilder _speexBuffer = BytesBuilder();

  void startEncodeTest() async {
    _speexBuffer.clear();
    final encoder = SpeexEncoderFFI();

    final frameSize = encoder.frameSize * 2; // 16-bit PCM
    Uint8List buffer = Uint8List(0);
    final pcmStream = pcmFileToStream('assets/1759820512419-record_demo.pcm', chunkSize: 640);
    int count = 0;

    pcmStream.listen((data) {
      buffer = Uint8List.fromList([...buffer, ...data]);
      while (buffer.length >= frameSize) {
        final frame = buffer.sublist(0, frameSize);
        print(count++);
        print("输入");
        print(frame);
        print("输入长度：${frame.length}");
        final encoded = encoder.encode(frame);
        print("输出");
        print(encoded);
        print("输出长度：${encoded.length}");
        _speexBuffer.add(encoded);
        // print('编码一帧 SPEEX 数据长度: ${encoded.length}');
        buffer = buffer.sublist(frameSize);
        // encoded 就是 Speex 数据，可以发送到服务器或写文件
      }
    });
  }

  final BytesBuilder _pcmBuffer = BytesBuilder();

  void startDecoderTest() {
    _pcmBuffer.clear();
    final decoder = SpeexDecoderFFI();
    final speexStream = speexFileToFrameStream('assets/iat_speex_wideband_16k.speex');
    speexStream.listen((speexFrame) {
      final pcmFrame = decoder.decode(speexFrame);
      _pcmBuffer.add(pcmFrame);
      print('解码一帧 PCM 数据长度: ${pcmFrame.length}');
    });
  }

  Future<void> uploadFile(Uint8List data, String fileName) async {
    try {
      // 1. 获取临时目录
      final tempDir = await getTemporaryDirectory();
      final filePath = '${tempDir.path}/$fileName';

      // 2. 将 Uint8List 写入本地文件
      final file = File(filePath);
      await file.writeAsBytes(data);

      // 3. 上传文件
      final dio = Dio();
      final formData = FormData.fromMap({
        'file': await MultipartFile.fromFile(filePath, filename: fileName),
      });

      final response = await dio.post(
        'http://10.34.41.160:8888/upload',
        data: formData,
      );

      print('上传成功: ${response.data}');
    } catch (e) {
      print('上传失败: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: () async {
                // RecordDemo.instance.startRecord();
                AiDeviceVoiceControllerManager.instance.start((VoiceControllerResult result) {
                  print(result);
                });
              },
              child: const Text("录音 转 speex 识别"),
            ),
            ElevatedButton(
              onPressed: () {
                // RecordDemo.instance.stopRecord();
                AiDeviceVoiceControllerManager.instance.stop();
              },
              child: const Text("停止录音"),
            ),
            ElevatedButton(
              onPressed: () {
                SoundDemo.instance.startStreamPlayer();
                final decoder = SpeexDecoderFFI();
                final speexStream = speexFileToFrameStream('assets/1760404701028-audio.speex');
                speexStream.listen((speexFrame) {
                  final pcmFrame = decoder.decode(speexFrame);
                  SoundDemo.instance.feedAudioChunk(pcmFrame);
                });
              },
              child: const Text("播放 speex 流"),
            ),
            ElevatedButton(
              onPressed: () {
                startEncodeTest();
              },
              child: const Text("pcm 转 speex"),
            ),
            ElevatedButton(
              onPressed: () {
                if (_speexBuffer.toBytes().isNotEmpty) {
                  uploadFile(_speexBuffer.toBytes(), "demo.speex");
                }
              },
              child: const Text("发送speex"),
            ),
            ElevatedButton(
              onPressed: () {
                startDecoderTest();
              },
              child: const Text("speex 转 pcm"),
            ),
            ElevatedButton(
              onPressed: () {
                if (_pcmBuffer.toBytes().isNotEmpty) {
                  uploadFile(_pcmBuffer.toBytes(), "demo.pcm");
                }
              },
              child: const Text("发送pcm"),
            ),
            ElevatedButton(
              onPressed: () async {

                final xf = DerucciIatStream();
                // final xf = XfIatStream();
                await xf.startRecognizeByAsset('assets/iat_speex_wideband_16k.speex');
              },
              child: const Text("语音文件识别"),
            ),
          ],
        ),
      ),
    );
  }
}
